package com.gagakuai.engine.impl.event;

import com.gagakuai.engine.delegate.event.AbstractActivitiEvent;
import com.gagakuai.engine.delegate.event.ActivitiEventListener;
import com.gagakuai.engine.delegate.event.ActivitiEventType;
import com.gagakuai.engine.exception.ActivitiIllegalArgumentException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;

/**
 * @program: common-starters
 * @description: 事件支持器
 * @author: houhong
 * @create: 2023-01-02 21:22
 **/
public class ActivitiEventSupport {

    private static final Logger logger = LoggerFactory.getLogger(ActivitiEventSupport.class);

    //全局监听器
    List<ActivitiEventListener> eventListeners;
    //具体事件对应的监听器
    Map<ActivitiEventType, List<ActivitiEventListener>> typedListeners;

    public ActivitiEventSupport() {
        this.eventListeners = new CopyOnWriteArrayList<>();
        this.typedListeners = new ConcurrentHashMap<>();
    }

    public synchronized void addEventListener(ActivitiEventListener listenerToAdd) {
        if (listenerToAdd == null) {
            throw new ActivitiIllegalArgumentException("Listener cannot be null.");
        }
        if (!eventListeners.contains(listenerToAdd)) {
            eventListeners.add(listenerToAdd);
        }
    }

    public synchronized void addEventListener(ActivitiEventListener listenerToAdd, ActivitiEventType... types) {
        if (listenerToAdd == null) {
            throw new ActivitiIllegalArgumentException("Listener cannot be null.");
        }

        if (types == null || types.length == 0) {
            addEventListener(listenerToAdd);

        } else {
            for (ActivitiEventType type : types) {
                addTypedEventListener(listenerToAdd, type);
            }
        }
    }

    public void removeEventListener(ActivitiEventListener listenerToRemove) {
        eventListeners.remove(listenerToRemove);

        for (List<ActivitiEventListener> listeners : typedListeners.values()) {
            listeners.remove(listenerToRemove);
        }
    }

    protected synchronized void addTypedEventListener(ActivitiEventListener listener, ActivitiEventType type) {
        List<ActivitiEventListener> listeners = typedListeners.get(type);
        if (listeners == null) {
            // Add an empty list of listeners for this type
            listeners = new CopyOnWriteArrayList<ActivitiEventListener>();
            typedListeners.put(type, listeners);
        }

        if (!listeners.contains(listener)) {
            listeners.add(listener);
        }
    }

    public void dispatchEvent(AbstractActivitiEvent event) {

        if (event == null) {
            throw new ActivitiIllegalArgumentException("Event cannot be null.");
        }

        if (event.getType() == null) {
            throw new ActivitiIllegalArgumentException("Event type cannot be null.");
        }

        //执行全局事件监听器
        if (!eventListeners.isEmpty()) {
            eventListeners.stream().forEach(eventListener -> {
                dispatchEvent(event, eventListener);
            });

        }

        //根据类型获取到具体到监听器
        List<ActivitiEventListener> activitiEventListeners = typedListeners.get(event.getType());

        if (!activitiEventListeners.isEmpty()) {
            activitiEventListeners.stream().forEach(activitiEventListener -> {
                dispatchEvent(event, activitiEventListener);
            });
        }


    }

    /**
     * 分发事件
     **/
    protected void dispatchEvent(AbstractActivitiEvent event, ActivitiEventListener listener) {

        try {
            listener.onEvent(event);
        } catch (Throwable t) {
            t.printStackTrace();
        }

    }


}